﻿using Co9320.NamaAlert;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using Co9320.NamaAlert.Model;

namespace TagServiceTest
{
    
    
    /// <summary>
    ///LexerTest のテスト クラスです。すべての
    ///LexerTest 単体テストをここに含めます
    ///</summary>
	[TestClass()]
	public class LexerTest
	{


		private TestContext testContextInstance;

		/// <summary>
		///現在のテストの実行についての情報および機能を
		///提供するテスト コンテキストを取得または設定します。
		///</summary>
		public TestContext TestContext
		{
			get
			{
				return testContextInstance;
			}
			set
			{
				testContextInstance = value;
			}
		}

		#region 追加のテスト属性
		// 
		//テストを作成するときに、次の追加属性を使用することができます:
		//
		//クラスの最初のテストを実行する前にコードを実行するには、ClassInitialize を使用
		//[ClassInitialize()]
		//public static void MyClassInitialize(TestContext testContext)
		//{
		//}
		//
		//クラスのすべてのテストを実行した後にコードを実行するには、ClassCleanup を使用
		//[ClassCleanup()]
		//public static void MyClassCleanup()
		//{
		//}
		//
		//各テストを実行する前にコードを実行するには、TestInitialize を使用
		//[TestInitialize()]
		//public void MyTestInitialize()
		//{
		//}
		//
		//各テストを実行した後にコードを実行するには、TestCleanup を使用
		//[TestCleanup()]
		//public void MyTestCleanup()
		//{
		//}
		//
		#endregion



		/// <summary>
		///Current のテスト
		///</summary>
		[TestMethod()]
		public void LexTest()
		{
			Lexer target = new Lexer("[hello]      [world] hoge piyo fuga hage");
			List<Token> ExpectedList = new List<Token>();
			ExpectedList.Add(new Token("[", TokenType.LeftBracket));
			ExpectedList.Add(new Token("hello", TokenType.String));
			ExpectedList.Add(new Token("]", TokenType.RightBracket));
			ExpectedList.Add(new Token("      ", TokenType.String));
			ExpectedList.Add(new Token("[", TokenType.LeftBracket));
			ExpectedList.Add(new Token("world", TokenType.String));
			ExpectedList.Add(new Token("]", TokenType.RightBracket));
			ExpectedList.Add(new Token(" hoge piyo fuga hage", TokenType.String));
			ExpectedList.Add(new Token(null, TokenType.EOF));
			int idx = -1;

			while (target.Next())
			{
				idx++;
				AreEqual(ExpectedList[idx], target.Current);
				AreEqual(ExpectedList[idx + 1], target.Peek);
			}
		}

		[TestMethod]
		public void IrregularTest()
		{
			string Sample = "hello \r\n world\r[hoge]\npiyo";
			
			Queue<Token> Exp = new Queue<Token>();
			Exp.Enqueue(new Token("hello ", TokenType.String));
			Exp.Enqueue(new Token("\r\n", TokenType.LineBreak));
			Exp.Enqueue(new Token(" world", TokenType.String));
			Exp.Enqueue(new Token("\r", TokenType.LineBreak));
			Exp.Enqueue(new Token("[", TokenType.LeftBracket));
			Exp.Enqueue(new Token("hoge", TokenType.String));
			Exp.Enqueue(new Token("]", TokenType.RightBracket));
			Exp.Enqueue(new Token("\n", TokenType.LineBreak));
			Exp.Enqueue(new Token("piyo", TokenType.String));
			Exp.Enqueue(new Token(null, TokenType.EOF));

			TestHead(Sample, Exp);
		}

		private void TestHead(string Sample, Queue<Token> ExpectedQueue)
		{
			Lexer lex = new Lexer(Sample);
			int index = 0;
			while (lex.Next())
			{
				Token Expected = ExpectedQueue.Dequeue();
				Assert.AreEqual<TokenType>(Expected.Type,lex.Current.Type,index++.ToString());
				if (Expected.Value == null)
				{
					Assert.IsNull(lex.Current.Value);
				}
			}

			Assert.AreEqual<TokenType>(ExpectedQueue.Peek().Type, lex.Current.Type);
			Assert.IsNull(lex.Current.Value);
			ExpectedQueue.Dequeue();

			Assert.AreEqual<int>(0, ExpectedQueue.Count);
		}

		private void AreEqual(Token Expected, Token Actual)
		{
			if (Expected != null && Actual != null)
			{
				Assert.AreEqual<TokenType>(Expected.Type, Actual.Type);
				Assert.AreEqual<string>(Expected.Value, Actual.Value);
			}
			else if (Expected==null && Actual==null)
			{
				return;
			}
			else
			{
				Assert.Fail();
			}
		}

		/// <summary>
		///Next のテスト
		///</summary>
		[TestMethod()]
		public void SkipNull()
		{
			Lexer target = new Lexer(null);

			for (int i = 0; i < 2; i++)
			{
				Assert.IsFalse(target.Next());
			}
		}

		/// <summary>
		///Lexer コンストラクタ のテスト
		///</summary>
		[TestMethod()]
		public void LexerConstructorTest()
		{
			Lexer target = new Lexer(null);
			target = new Lexer("hoge");
			target = new Lexer("[piyo] ll");

		}
	}
}
